//
//  MTBeacon4Protocol.swift
//  MTBLETools
//
//  Created by 方强 on 16/10/27.
//  Copyright © 2016年 MT. All rights reserved.
//

import UIKit

public class MTBeacon4Protocol {
    private var transprotocolhelp:TransferprotocolHelp!;
    
    private let transcallback = TransferprotocolHelp.Callback();
    
    public init() {
        self.transprotocolhelp = TransferprotocolHelp();
        transcallback.onGetcmd = onGetcmd;
        transprotocolhelp.setCallback(callback: transcallback);
        
    }
    
    // 读取广播数据
    public static func getPrivateBeaconParams(id:Int) -> Data?{
        var datas:[UInt8] = [UInt8](repeating: 0, count: 3);
        var lenght:Int = 0;
        datas[lenght] = 0x0E;  lenght += 1;// 命令
    
        datas[lenght] = UInt8(id & 0xFF);  lenght += 1;// ID
    
        datas[datas.count - 1] = TransferprotocolHelp.getLRCCheckByte(datas: datas, lenght: datas.count - 1)!; // 添加校验
        datas = TransferprotocolHelp.packgeDatas(datas: datas)!;
        return Data(bytes:datas);
    }
    
    // 0X4C, 0X00, 苹果ID
    // 0X02, 0X15, IBeaconID
    // 0XFD, 0XA5, 0X06, 0X93, UUID
    // 0XA4, 0XE2, \
    // 0X4F, 0XB1, \
    // 0XAF, 0XCF, \
    // 0XC6, 0XEB, 0X07, 0X64, 0X78, 0X25,\
    // 0X27, 0X12,\ major
    // 0X21, 0X1F,\ minor
    // 0XC0\ measurepower
    // 设置广播数据
    public static func setPrivateBeaconParams(mPrivateBeaconParams: MTBeaconInfModel) -> Data?{
        var datas:[UInt8] = [UInt8](repeating: 0, count: 29);
        var lenght:Int = 0;
        datas[lenght] = 0x0F; lenght += 1;// 命令
    
        datas[lenght] = UInt8((mPrivateBeaconParams.getBeaconid() >> 0) & 0xFF); lenght += 1;// ID号
        datas[lenght] = UInt8((mPrivateBeaconParams.getWeight() >> 0) & 0xFF);lenght += 1;// 广播频率
    
        datas[lenght] = 0x4C; lenght += 1;// 苹果ID
        datas[lenght] = 0x00;lenght += 1;
    
        datas[lenght] = 0x02; lenght += 1;// IBeacon ID
        datas[lenght] = 0x15;lenght += 1;
    
        let uuid:[UInt8] = MTTools.converDataToByteArray(data: MTTools.convertStringToByteArray(str: mPrivateBeaconParams.getBeaconUUID()!)!); // UUID
        MTTools.arraycopy(src: uuid, srcPos: 0, dst: &datas, dstPos: lenght, length: uuid.count);
        lenght += uuid.count;
    
        datas[lenght] = MTTools.converHiUint16(i: mPrivateBeaconParams.getMajor()); lenght += 1;// major
        datas[lenght] = MTTools.converLoUint16(i: mPrivateBeaconParams.getMajor());lenght += 1;
        
        datas[lenght] = MTTools.converHiUint16(i: mPrivateBeaconParams.getMinor()); lenght += 1;// major
        datas[lenght] = MTTools.converLoUint16(i: mPrivateBeaconParams.getMinor());lenght += 1;
    
        datas[lenght] = UInt8(256 - mPrivateBeaconParams.getMeasuedPower()); lenght += 1;// txpower
    
        datas[datas.count - 1] = TransferprotocolHelp.getLRCCheckByte(datas: datas, lenght: datas.count - 1)!; // 添加校验
        datas = TransferprotocolHelp.packgeDatas(datas: datas)!;
        return Data(bytes:datas);
    }
    
    // 读取Beacon公共参数
    public static func getPublicBeaconParams() -> Data?{
        var datas:[UInt8] = [UInt8](repeating: 0, count: 2);
        var lenght:Int = 0;
        datas[lenght] = 0x09; lenght += 1; // 命令
    
        datas[datas.count - 1] = TransferprotocolHelp.getLRCCheckByte(datas: datas, lenght: datas.count - 1)!; // 添加校验
        datas = TransferprotocolHelp.packgeDatas(datas: datas)!;
        return Data(bytes:datas);
    }
    
    // 设置Beacon公共参数
    public static func setPublicBeaconParams(mPublicBeaconParams: MTBeaconInfModel) -> Data?{
        var datas:[UInt8] = [UInt8](repeating: 0, count: 4);
        var lenght:Int = 0;
        datas[lenght] = 0x0A;  lenght += 1;// 命令
    
        datas[lenght] = MTTools.converLoUint16(i: (mPublicBeaconParams.getSendhz() / 100)); lenght += 1;
    
        datas[lenght] = MTTools.converLoUint16(i: mPublicBeaconParams.getSendpower()); lenght += 1;// 发射功率
    
        datas[datas.count - 1] = TransferprotocolHelp.getLRCCheckByte(datas: datas, lenght: datas.count - 1)!; // 添加校验
    
        datas = TransferprotocolHelp.packgeDatas(datas: datas)!;

        return Data(bytes:datas);
    }
    
    // 部署
    public static func setDeverlop(id:Int, msg:String) -> Data?{
//        var datas:[UInt8]!;
//        var lenght:Int = 0;
    
        if (id == 66) {
            let msg_byte = msg.data(using: String.Encoding.utf8);
            var datas = [UInt8](repeating: 0, count: msg_byte!.count+3);
            var lenght:Int = 0;
    
            datas[lenght] = 0x10;  lenght += 1;// 命令
            datas[lenght] = UInt8((id >> 0) & 0xFF); lenght += 1;// 部署方式
            MTTools.arraycopy(src: MTTools.converDataToByteArray(data: msg_byte!), srcPos: 0, dst: &datas, dstPos: lenght, length: msg_byte!.count);
            
            datas[datas.count - 1] = TransferprotocolHelp.getLRCCheckByte(datas: datas, lenght: datas.count - 1)!; // 添加校验
            
            datas = TransferprotocolHelp.packgeDatas(datas: datas)!;
            return Data(bytes:datas);
        } else {
            var datas = [UInt8](repeating: 0, count: 3);
            var lenght:Int = 0;
            datas[lenght] = 0x10; lenght += 1;// 命令
            datas[lenght] = UInt8((id >> 0) & 0xFF); lenght += 1;// 部署方式
            
            datas[datas.count - 1] = TransferprotocolHelp.getLRCCheckByte(datas: datas, lenght: datas.count - 1)!; // 添加校验
            
            datas = TransferprotocolHelp.packgeDatas(datas: datas)!;
            return Data(bytes:datas);
        }
    }
    
    // 密码验证
    public static func verifyPwd(pwd:String) -> Data?{
    
        let pwd_byte = pwd.data(using: String.Encoding.utf8);
        
        var datas:[UInt8] = [UInt8](repeating: 0, count: pwd_byte!.count + 2);

        var lenght:Int = 0;
        datas[lenght] = 0x0D;  lenght += 1;// 命令
    
        MTTools.arraycopy(src: MTTools.converDataToByteArray(data: pwd_byte!), srcPos: 0, dst: &datas, dstPos: lenght, length: pwd_byte!.count); // 密码
    
        datas[datas.count - 1] = TransferprotocolHelp.getLRCCheckByte(datas: datas, lenght: datas.count - 1)!; // 添加校验
    
        datas = TransferprotocolHelp.packgeDatas(datas: datas)!;
        return Data(bytes:datas);
    }
    
    // 读取固件版本号
    public static func getVersion() -> Data?{
        var datas:[UInt8] = [UInt8](repeating: 0, count: 2);
        var lenght:Int = 0;
    
        datas[lenght] = 0x06; lenght += 1;
    
        datas[datas.count - 1] = TransferprotocolHelp.getLRCCheckByte(datas: datas, lenght: datas.count - 1)!;  // 添加校验
    
        datas = TransferprotocolHelp.packgeDatas(datas: datas)!;
        return Data(bytes:datas);
    }
    
    // 接收短数据进入协议进行拆包
    public func reviceDatas(datas:Data) {
        transprotocolhelp.putDatas(datas: datas);
    }
    
    // 接收数据回调
    public func onGetcmd(cmd:Data) {
        print("解包数据->\(MTTools.convertDataToString(data: cmd))");
        if (!TransferprotocolHelp.checkErro(datas: cmd)) { // 校验错误
            MTTools.logout(log: "onGetcmd校验错误");
            return;
        }
//        MTTools.logout(log: "解包数据->\(MTTools.converDataToByteArray(data: cmd))");
        analysisReviceCmd(cmd: cmd);
    }
    
    // 设置回调数据
    private var mProtocolCallBack:MTBeacon4Protocol_CallBack?;
    
    public func setCallBack(mProtocolCallBack:MTBeacon4Protocol_CallBack) {
        self.mProtocolCallBack = mProtocolCallBack;
    }
    
    // 获取错误解析
    private static let ERROMSG = [ "指令校验失败", "指令ID错误", "指令长度错误", "提醒器内存不足", "指令参数超出范围", "指令参数错误", "需要验证密码",
    "密码验证失败", "文件名错误", "文件过大" ];
    
    // 分析数据
    private func analysisReviceCmd(cmd:Data) {
    
        var erro_flag = false;
        var erromsg = "";
        var realcmd = cmd[0];
        if (cmd[0] > 0x80) {
            if (cmd.count < 4) {
				return;
            }
            erro_flag = true;
            erromsg = MTBeacon4Protocol.ERROMSG[Int(cmd[1])-1];
            realcmd = UInt8(realcmd & 0x7F);
        }
    
        if (realcmd == 0x0E) { // 读取广播数据
    
            if (erro_flag) {
				mProtocolCallBack?.onGetPrivateBeaconParams?(nil, false, 0);
				return;
            }
    
            if (cmd.count != 29) {
				let mPrivateBeaconParams = MTBeaconInfModel();
				mPrivateBeaconParams.setBeaconid(beaconid: MTTools.convertUint8(b: cmd[1]));
				mProtocolCallBack?.onGetPrivateBeaconParams?(mPrivateBeaconParams, true, 0);
				return;
            }
    
            let mPrivateBeaconParams = MTBeaconInfModel();
            mPrivateBeaconParams.setBeaconid(beaconid: MTTools.convertUint8(b: cmd[1]));
            mPrivateBeaconParams.setWeight(weight: MTTools.convertUint8(b: cmd[2]));
            let uuid_str = String(format: "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X", cmd[7],cmd[8],cmd[9],cmd[10],cmd[11],cmd[12],cmd[13],cmd[14],cmd[15],cmd[16],cmd[17],cmd[18],cmd[19],cmd[20],cmd[21],cmd[22]);
            mPrivateBeaconParams.setBeaconUUID(beaconUUID: uuid_str);
            mPrivateBeaconParams.setMajor(major: MTTools.convertUint16(hb: cmd[23], lb: cmd[24]));
            mPrivateBeaconParams.setMinor(minor: MTTools.convertUint16(hb: cmd[25], lb: cmd[26]));
            mPrivateBeaconParams.setMeasuedPower(measuedPower: 256-Int(cmd[27]));
            mProtocolCallBack?.onGetPrivateBeaconParams?(mPrivateBeaconParams, true, 0);
            return;
        }
    
        if (cmd[0] == 0x0F) { // 设置广播参数
            if (erro_flag) {
                mProtocolCallBack?.onSetPrivateBeaconParams?(false, 0);
				return;
            }
    
            mProtocolCallBack?.onSetPrivateBeaconParams?(true, 0);
            return;
        }
    
        if (cmd[0] == 0x09) { // 读取Beacon公共参数
            if (erro_flag || (cmd.count != 4)) {
				mProtocolCallBack?.onGetPublicBeaconParams?(nil, false, 0);
				return;
            }
    
            let mPublicBeaconParams = MTBeaconInfModel();
            mPublicBeaconParams.setSendhz(sendhz: MTTools.convertUint8(b: cmd[1]) * 100);
            mPublicBeaconParams.setSendpower(sendpower: MTTools.convertUint8(b: cmd[2]));
            mProtocolCallBack?.onGetPublicBeaconParams?(mPublicBeaconParams, true, 0);
            return;
        }
    
        if (cmd[0] == 0x0A) { // 设置Beacon公共参数
            if (erro_flag) {
				mProtocolCallBack?.onSetPublicBeaconParams?(false, 0);
				return;
            }
    
            mProtocolCallBack?.onSetPublicBeaconParams?(true, 0);
            return;
        }
    
        if (cmd[0] == 0x10) { // 设置部署模式
            if (erro_flag) {
				mProtocolCallBack?.onSetDeverlop?(false, 0);
				return;
            }
            mProtocolCallBack?.onSetDeverlop?(true, 0);
            return;
        }
    
        if (cmd[0] == 0x0D) { // 密码验证
            if (erro_flag) {
				mProtocolCallBack?.onVerifyPwd?(false, 0);
				return;
            }
    
            mProtocolCallBack?.onVerifyPwd?(true, 0);
            return;
        }
    
        if (cmd[0] == 0x06) { // 读取固件版本号
            if (erro_flag || (cmd.count < 2)) {
				mProtocolCallBack?.onGetVersion?(nil, false, 0);
				return;
            }
            
            var version_byte = [UInt8](repeating: 0, count: cmd.count - 2);
            let cmd_byte = MTTools.converDataToByteArray(data: cmd);
            MTTools.arraycopy(src: cmd_byte, srcPos: 1, dst: &version_byte, dstPos: 0, length: version_byte.count);
            
            let version_str = String(bytes: version_byte, encoding: String.Encoding.utf8);
    
            mProtocolCallBack?.onGetVersion?(version_str, true, 0);
    
            return;
        }
    }
}

// 回调
public class MTBeacon4Protocol_CallBack: NSObject {
    public override init() {
        super.init();
    }
    
    var unKnowDatas:((Data)->Void)?;
    
    var onGetPrivateBeaconParams:((MTBeaconInfModel?, Bool, Int)->Void)?;
    
    var onSetPrivateBeaconParams:((Bool, Int)->Void)?;
    
    var onGetPublicBeaconParams:((MTBeaconInfModel?, Bool, Int)->Void)?;
    
    var onSetPublicBeaconParams:((Bool, Int)->Void)?;
    
    var onSetDeverlop:((Bool, Int)->Void)?;
    
    var onVerifyPwd:((Bool, Int)->Void)?;
    
    var onGetVersion:((String?, Bool, Int)->Void)?;
}
